package ccm.component.image;

import ccm.common.ReceiveDataEvent;
import ccm.common.ReceiveDataListener;
import ccm.common.TooManyListenerException;

import java.awt.image.BufferedImage;

public class ImageDecoder implements ReceiveDataListener
{
    /**
     * 接收缓冲
     */
    protected final int[]                receiveBuf;
    /**
     * 接收缓冲起始
     */
    protected       int                  receiveBufStart;
    /**
     * 接收状态
     */
    protected       ReceiveState         receiveState;
    /**
     * 当前接收横坐标
     */
    protected       int                  receivingI;
    /**
     * 当前接收纵坐标
     */
    protected       int                  receivingJ;
    /**
     * 接收图片缓冲
     */
    protected       BufferedImage        image;
    /**
     * 接收到图片监听器
     */
    protected       ReceiveImageListener receiveImageListener;

    protected int successCnt;
    protected int totalCnt;

    protected int imageWidth =188;
    protected int imageHeight=120;


    public ImageDecoder()
    {
        receiveBuf     =new int[4];
        receiveBufStart=0;
        receiveState   =ReceiveState.RECEIVING_HEAD;
    }

    /**
     * 接收到数据事件
     */
    public void receiveData(ReceiveDataEvent event)
    {
        for(byte datum: event.getData())
        {
            int dat=Byte.toUnsignedInt(datum);
            switch(receiveState)
            {
                case RECEIVING_HEAD:
                    receiveBuf[receiveBufStart]=dat;
                    receiveBufStart=(receiveBufStart+1)%receiveBuf.length;
                    if(receiveBuf[(receiveBufStart)%receiveBuf.length]==0x00&&receiveBuf[(receiveBufStart+1)%receiveBuf.length]==0xFF&&receiveBuf[(receiveBufStart+2)%receiveBuf.length]==0x01&&receiveBuf[(receiveBufStart+3)%receiveBuf.length]==0x01)
                    {
                        receiveState=ReceiveState.RECEIVING_IMAGE;
                        receivingI  =0;
                        receivingJ  =0;
                        image       =new BufferedImage(imageWidth,imageHeight,BufferedImage.TYPE_INT_RGB);
                    }
                    break;
                case RECEIVING_IMAGE:
                    if(image!=null)
                    {
                        image.setRGB(receivingI,receivingJ,(((dat)&0XFF)<<16)|(((dat)&0XFF)<<8)|(((dat)&0XFF)));
                        ++receivingI;
                        if(receivingI>=imageWidth)
                        {
                            receivingI=0;
                            ++receivingJ;
                        }
                        if(receivingJ>=imageHeight)
                        {
                            receiveState   =ReceiveState.RECEIVING_TAIL;
                            receiveBufStart=0;
                        }
                    }
                    else
                        receiveState=ReceiveState.RECEIVING_HEAD;
                    break;
                case RECEIVING_TAIL:
                    receiveBuf[receiveBufStart]=dat;
                    receiveBufStart=(receiveBufStart+1)%4;
                    if(receiveBufStart==0)
                    {
                        ++totalCnt;
                        if(receiveBuf[(receiveBufStart)%4]==0x01&&receiveBuf[(receiveBufStart+1)%4]==0x01&&receiveBuf[(receiveBufStart+2)%4]==0xFF&&receiveBuf[(receiveBufStart+3)%4]==0x00&&receiveImageListener!=null)
                        {
                            receiveImageListener.receiveImage(new ReceiveImageEvent(this,image));
                            ++successCnt;
                        }
                        receiveState=ReceiveState.RECEIVING_HEAD;
                        System.out.println(String.format("%.2f%%",100*((double)successCnt)/totalCnt));
                    }
                    break;
            }

        }
    }

    /**
     * 添加图片接收监听器
     *
     * @param listener 监听器
     * @throws TooManyListenerException 监听器过多时抛出此异常
     * @throws NullPointerException     监听器为null时抛出此异常
     * @implNote 只支持一个监听器
     */
    public void addReceiveImageListener(ReceiveImageListener listener) throws TooManyListenerException, NullPointerException
    {
        if(listener==null)
            throw new NullPointerException();
        if(receiveImageListener!=null)
            throw new TooManyListenerException();
        receiveImageListener=listener;
    }

    protected enum ReceiveState
    {
        RECEIVING_HEAD,RECEIVING_IMAGE,RECEIVING_TAIL,
    }
}
